import React from 'react';
import { Button, Drawer, Icon, Modal } from 'antd';

import {
  FileTypeEnum,
  SessionAnswerGenerateTypeEnum,
  SessionMessageDirectionEnum,
  SessionMessageStatusEnum,
  SessionMessageTypeEnum,
} from '@/common/constant/service.enum';
import {
  FILE_URL,
  ROBOT_HOST,
  USER_AVATAR,
} from '@/common/constant/session';
import utils from '@/common/utils/session';
import { getDocFileInfo, getSessionDetail } from '@/services/datastatistics';
import Message from './Message';

import MarkdownRenderer from '@/components/common/MarkdownRenderer';
import ChoiseSuggestionList from './ChoiseSuggestionList';

import styles from './index.module.less';

interface IProp {
  applicationId: string;
  sessionId: string;
  userId: string;
}

interface IState {
  messageList: Message[];
  isAttachmentListExpand: boolean;
  attachmentModalVisible: boolean;
  currentAttachment: Session.ISessionDetailAttachment;
  paragraphSliceShowLength: number;
  currentParagraphSlice: Session.ISessionDetailAnswerDataSourceParagraph;
  paragraphDrawerVisible: boolean;
}

class SessionContext extends React.Component<IProp, IState> {
  constructor(props: IProp) {
    super(props);
    this.state = {
      messageList: [],
      isAttachmentListExpand: false,
      attachmentModalVisible: false,
      currentAttachment: null,
      paragraphSliceShowLength: 1,
      currentParagraphSlice: null,
      paragraphDrawerVisible: false,
    };
  }

  componentDidMount(): void {
    this.getSessionContextDetail();
    window.addEventListener('click', this.registerReferenceButtonHandler);
  }

  componentWillUnmount(): void {
    window.removeEventListener('click', this.registerReferenceButtonHandler);
  }

  /**
   * @mounted
   * 获取会话详情数据
   * @returns 
   */
  getSessionContextDetail = async () => {
    const { applicationId, sessionId } = this.props;

    if (!applicationId || !sessionId) {
      return;
    }

    const result = await getSessionDetail({
      applicationId,
      sessionId,
    });
    this.setState({
      messageList: [],
    }, () => {
      this.resolveSessionDetailData(result, sessionId);
      this.setState({}, () => {
        const container = document.querySelector('#session-context')?.parentElement;
        if (container) {
          container.scrollTop = container.scrollHeight;
        }
      });
    });
  }

  /**
   * @mounted
   * 处理会话详情数据，方便渲染
   * 逻辑是从咨询窗项目直接复制过来的
   * TODO: 删除、调整不必要的数据处理
   * @param sessionDetailList 
   * @param sessionId 
   * @returns 
   */
  resolveSessionDetailData = (sessionDetailList: Session.ISessionDetail[], sessionId: string) => {
    if (sessionDetailList.length === 0) {
      return;
    }

    for (let i = sessionDetailList.length - 1; i >= 0; i--) {
      const detail = sessionDetailList[i];
      const time = new Date(detail.time);

      /**
       * 处理答案
       */
      detail.choices = [];
      detail.suggestions = [];
      detail.mainQuestion = detail.question;
      detail.modelName = detail.modelName;
      detail.chatId = detail.id;
      // 将附件转义
      if (JSON.parse(detail.attachments || '[]').length > 0) {
        detail.attachmentList = JSON.parse(detail.attachments);
      }
      // 处理 JSON 类型的答案
      if (utils.isObjectJson(detail.answer)) {
        detail.answer = JSON.parse(detail.answer).data?.guide ?? '';
        detail.answerType = 'json';
      }
      // 处理答案中的引用切片
      detail.answer = detail.answer.replace(/\[\[(\d+)\]\]/g, `<span className='refer-btn' data-index='${i * 2 + 1}'>$1</span>`);
      const answerMessage = {
        sessionId,
        answerType: detail.answerType,
        // customerId: commonDataClass.customer.customerId,
        messageId: 'MessageId' + utils.createMessageID(),
        messageContent: JSON.stringify(detail),
        messageDirection: SessionMessageDirectionEnum.客服发送给用户,
        messageStatus: 10,
        messageType: SessionMessageTypeEnum.机器人回复消息,
        agentId: detail.agentId,
        agentName: detail.agentName,
        resolveFlag: detail.resolveFlag,
        comment: detail.comment,
        reason: detail.reason,
        readTime: time,
        recallTime: time,
        sendTime: time,
      };

      /**
       * 处理问题
       * 问题和答案的插入顺序有影响，所以 setState 分开处理
       */
      if (detail.question === 'qizhi_welcome' || detail.question === '欢迎语') {
        this.setState(({ messageList }) => ({
          messageList: [new Message(answerMessage), ...messageList],
        }));
        return;
      }

      const questionMessage = {
        sessionId,
        fileDocList: [],
        fileImgData: { id: '', name: null, url: '' },
        messageId: 'MessageId' + utils.createMessageID(),
        messageContent: detail.question,
        messageDirection: SessionMessageDirectionEnum.用户发送给客服,
        messageStatus: 10,
        messageType: SessionMessageTypeEnum.文本,
        agentId: detail.agentId,
        agentName: detail.agentName,
        resolveFlag: detail.resolveFlag,
        comment: detail.comment,
        reason: detail.reason,
        recallTime: time,
        sendTime: time,
      };
      // 处理问题中的文档
      if (JSON.parse(detail.docs || '[]').length > 0) {
        questionMessage.fileDocList = JSON.parse(detail.docs).map((doc: Session.ISessionDetailDoc) => ({
          ...doc,
          isKnowledgeBase: true,
          categoryFlag: `${doc.categoryFlag}` === 'true',
        }));
      };
      // 处理问题中的图片
      if (JSON.parse(detail.images || '[]').length > 0) {
        questionMessage.fileImgData = { id: '', name: null, url: JSON.parse(detail.images)[0] };
      };
      this.setState(({ messageList }) => ({
        messageList: [new Message(questionMessage), new Message(answerMessage), ...messageList],
      }));
    }
  }

  /**
   * @mounted
   * 注册引用片段角标的点击功能
   * markdown 文本答案的内容由后端生成，并交由 VueMarkdown 组件渲染
   * 前端须在外层组件注册 window.click 事件进行监听处理
   */
  registerReferenceButtonHandler = (event) => {
    const target = event && event.target as HTMLElement;
    event.stopPropagation();
    if (!target || target.className !== 'refer-btn') {
      return;
    }
    const messageIndex = parseInt(target.getAttribute('data-index'));
    const sourceIndex = parseInt(target.innerText);
    try {
      const { messageList } = this.state;
      if (!messageList[messageIndex].messageContent) {
        return;
      }
      const messageContent = JSON.parse(messageList[messageIndex].messageContent);
      const paragraph = messageContent.answerDataSourceParagraphList[sourceIndex - 1] || null;
      if (!paragraph) {
        return;
      }
      this.handleParagraphDrawerShow(paragraph);
    } catch (e) {
      console.error(e);
    }
  }

  /**
   * 附件文档相关逻辑
   */
  handleAttachmentPreview = async (attachment: Session.ISessionDetailAttachment) => {
    const { userId } = this.props;

    switch (`${attachment.fileType}`) {
      case FileTypeEnum.其它:
        utils.getBlobFromUrl(`${ROBOT_HOST}/cloud/doc/downloadFile?id=${attachment.filePath}`, (blob) => {
          utils.downFileBlob(blob, attachment.fileName);
        });
        break;
      case FileTypeEnum.视频:
      case FileTypeEnum.图片:
        const result = await getDocFileInfo({ id: attachment.fileId });
        if (result.docType) {
          this.setState({
            attachmentModalVisible: true,
            currentAttachment: attachment,
          });
        } else {
          this.setState({
            attachmentModalVisible: true,
          });
        }
        break;
      case FileTypeEnum.互联网问答:
        window.open(attachment.filePath, '_blank');
        break;
      default:
        const url = `${location.origin}/preview/doc/${attachment.fileId}?docType=${attachment.fileType}&userId=${userId}`;
        window.open(url, '_blank');
        break;
    }
  }
  downLoadImgOrVideo = (attachment: Session.ISessionDetailAttachment) => {
    utils.getBlobFromUrl(`${ROBOT_HOST}/cloud/doc/downloadFile?id=${attachment.filePath}`, (blob) => {
      utils.downFileBlob(blob, attachment.fileName);
    });
  }
  handleAttachmentModalClose = () => {
    this.setState({
      attachmentModalVisible: false,
      currentAttachment: null,
    });
  }
  handleAttachmentListExpand = (event: React.MouseEvent<HTMLElement>) => {
    event.stopPropagation();
    this.setState({
      isAttachmentListExpand: true,
    });
  }

  /**
   * 引用切片相关逻辑
   */
  handleParagraphSliceShowLengthChange = (length: number) => {
    this.setState({
      paragraphSliceShowLength: length,
    });
  }
  handleParagraphDrawerShow = (paragraph: Session.ISessionDetailAnswerDataSourceParagraph) => {
    this.setState({
      currentParagraphSlice: paragraph,
      paragraphDrawerVisible: true,
    });
  }
  handleParagraphDrawerClose = () => {
    this.setState({
      currentParagraphSlice: null,
      paragraphDrawerVisible: false,
    });
  }

  render() {
    const {
      messageList,
      isAttachmentListExpand, attachmentModalVisible, currentAttachment,
      paragraphSliceShowLength, currentParagraphSlice, paragraphDrawerVisible,
    } = this.state;

    return (
      <ul id='session-context' className={styles['session-context']}>
        {messageList.map((message, index) => {
          const isQuestionShow = message.messageDirection === SessionMessageDirectionEnum.用户发送给客服;
          const isMessageContentObjectJson = utils.isObjectJson(message.messageContent);
          const parsedMessageContent = isMessageContentObjectJson && JSON.parse(message.messageContent);
          const isMessageContentNotForWelcome = isMessageContentObjectJson && parsedMessageContent.mainQuestion !== 'qizhi_welcome';
          const isValidAnswer = !isMessageContentObjectJson || isMessageContentNotForWelcome;
          const isAnswerShow =
            message.messageDirection === SessionMessageDirectionEnum.客服发送给用户 &&
            message.messageType !== SessionMessageTypeEnum.机器人待回复动画 &&
            message.messageStatus != SessionMessageStatusEnum.撤回 &&
            isValidAnswer;
          const answerAvatar = index + 1 === messageList.length
            ? '/session/chatComplete.png'
            : '/session/chatHistory.png';

          return (
            <li key={message.id + message.messageId} className={styles['message-item']}>
              {/* 渲染用户提问 */}
              {isQuestionShow && (
                <div className={styles['chat-item-box']}>
                  {/* 用户-头像 */}
                  <img className={styles['avatar-image']} src={FILE_URL + USER_AVATAR} />
                  {/* 用户-问题 */}
                  <div className={styles['chat-item-right']}>
                    <div className={styles['chat-item-answer']}>
                      <p dangerouslySetInnerHTML={{ __html: message.getHtml() }}></p>
                    </div>
                    {message.fileImgData?.url?.length > 0 && (
                      <div className={styles['file-corridor']}>
                        <span>上传的图片：</span>
                        <div className={`${styles['file-item-wrapper']} ${styles['file-image-wrapper']}`}>
                          <img className={styles['file-item-image']}
                            src={message.fileImgData.id === '' && !message.fileImgData.name ? message.fileImgData.url : FILE_URL + message.fileImgData.url}
                          />
                        </div>
                      </div>
                    )}
                    {message.fileDocList?.length > 0 && (
                      <div className={styles['file-corridor']}>
                        <span>上传的文档：</span>
                        {message.fileDocList.map((file: Session.ISessionDetailDoc) => {
                          const fileIcon = file.isKnowledgeBase && file.categoryFlag
                            ? '/session/h5Fold.png'
                            : `${file.type}` === FileTypeEnum.WORD
                              ? '/session/h5Word.png'
                              : `${file.type}` === FileTypeEnum.EXCEL
                                ? '/session/h5Excel.png'
                                : `${file.type}` === FileTypeEnum.PPT
                                  ? '/session/h5PPT.png'
                                  : `${file.type}` === FileTypeEnum.PDF
                                    ? '/session/h5Pdf.png'
                                    : `${file.type}` === FileTypeEnum.TXT
                                      ? '/session/h5Txt.png'
                                      : `${file.type}` === FileTypeEnum.附件
                                        ? '/session/fileDoc.png'
                                        : '/session/h5None.png';

                          return (
                            <div className={`${styles['file-item-wrapper']} ${styles['file-doc-wrapper']}`} key={file.id}>
                              <img src={fileIcon} />
                              <span>{file.name}</span>
                            </div>
                          );
                        })}
                      </div>
                    )}
                  </div>
                </div>
              )}
              {/* 渲染客服/机器人回答 - 非欢迎语 */}
              {isAnswerShow && (
                <div className={styles['chat-item-box']}>
                  {/* 客服/机器人-头像 */}
                  <img className={styles['avatar-image']} src={answerAvatar} />
                  {/* 客服/机器人-回答 */}
                  <div className={styles['chat-item-right']}>
                    <div className={styles['chat-item-answer']}>
                      {isMessageContentObjectJson && parsedMessageContent.answerSource === 'Chat' ? (
                        <div className={`${styles['chat-answer-part']}`}>
                          {/* 渲染 Markdown */}
                          <MarkdownRenderer
                            markdown={parsedMessageContent.answer.replace(/<script/g, `<code>< script`).replace(/<\/script>/g, `</ script></code>`)}
                          />
                          {/* 关联/词槽选项 */}
                          {message.showType() && (
                            <ChoiseSuggestionList message={message} />
                          )}
                        </div>
                      ) : !message.answerType ? (
                        <div className={styles['chat-answer-part']}>
                          {/* 渲染文字答案 */}
                          <p dangerouslySetInnerHTML={{ __html: message.getHtml() }}></p>
                          {/* 关联/词槽选项 */}
                          {message.showType() && (
                            <ChoiseSuggestionList message={message} />
                          )}
                        </div>
                      ) : message.answerType === 'json' ? (
                        <div className={styles['chat-answer-part']}>
                          {/* 渲染文字答案 */}
                          <p dangerouslySetInnerHTML={{ __html: message.getHtml() }}></p>
                        </div>
                      ) : null}
                      {/* 附件文档信息（attachmentList） */}
                      {
                        isMessageContentObjectJson &&
                        parsedMessageContent.attachmentList?.length > 0 && (
                          <div className={styles['attachment-list-wrapper']}>
                            <ul className={`${styles['attachment-grid']} ${isAttachmentListExpand ? styles['expand'] : ''}`}>
                              {parsedMessageContent.attachmentList.map((attachment: Session.ISessionDetailAttachment) => {
                                const fileIcon = `${attachment.fileType}` === FileTypeEnum.WORD
                                    ? '/session/h5Word.png'
                                    : `${attachment.fileType}` === FileTypeEnum.EXCEL
                                      ? '/session/h5Excel.png'
                                      : `${attachment.fileType}` === FileTypeEnum.PPT
                                        ? '/session/h5PPT.png'
                                        : `${attachment.fileType}` === FileTypeEnum.PDF
                                          ? '/session/h5Pdf.png'
                                          : `${attachment.fileType}` === FileTypeEnum.TXT
                                            ? '/session/h5Txt.png'
                                            : `${attachment.fileType}` === FileTypeEnum.互联网问答
                                              ? '/session/h5Url.png'
                                              : '/session/h5None.png';

                                return (
                                  <li key={attachment.fileId + attachment.fileName} className={styles['attachment-item']}
                                    onClick={() => this.handleAttachmentPreview(attachment)}
                                  >
                                    <img src={fileIcon} className={styles['item-image']} />
                                    <span className={styles['item-name']}>{attachment.fileName}</span>
                                  </li>
                                );
                              })}
                            </ul>
                            {parsedMessageContent.attachmentList.length > 4 && (
                              <Button className={`${styles['attachment-collapse-button']} ${isAttachmentListExpand ? styles['collapse'] : ''}`}
                                onClick={this.handleAttachmentListExpand}
                              >
                                更多
                              </Button>
                            )}

                            <Modal
                              centered={true}
                              closable={false}
                              footer={null}
                              visible={attachmentModalVisible}
                              bodyStyle={currentAttachment ? {
                                maxHeight: '500px',
                                overflow: 'auto',
                              } : {
                                height: '320px',
                              }}
                              onCancel={this.handleAttachmentModalClose}
                            >
                              <div slot="title">
                                <div style={{ display: 'flex', gap: '12px', lineHeight: '24px', }}>
                                  <span style={{ flex: 1 }}>图片/视频预览</span>
                                  <span
                                    style={{
                                      display: 'inline-block',
                                      margin: '-16px 0',
                                      marginRight: '-24px',
                                      width: '70px',
                                      height: '56px',
                                      lineHeight: '56px',
                                    }}
                                  >
                                    {currentAttachment ? (
                                      <span style={{ display: 'inline-block', width: '25px', textAlign: 'center', }}>
                                        <Icon type='download' onClick={() => this.downLoadImgOrVideo(currentAttachment)} />
                                      </span>
                                    ) : (
                                      <span style={{ display: 'inline-block', paddingRight: '16px', width: '40px', textAlign: 'center' }}>
                                        <Icon type='close' onClick={this.handleAttachmentModalClose} />
                                      </span>
                                    )}
                                  </span>
                                </div>
                              </div>
                              {currentAttachment ? (
                                <div style={{ textAlign: 'center' }}>
                                  {currentAttachment.fileType === 8 && (
                                    <img src={`${FILE_URL}/cloud/doc/previewFileByPath?path=${currentAttachment.filePath}`} width='85%' />
                                  )}
                                  {currentAttachment.fileType === 9 && (
                                    <video width='100%' height='100%' controls>
                                      <source src={`${FILE_URL}/cloud/doc/downloadFile?id=${currentAttachment.filePath}`} type='video/mp4' />
                                    </video>
                                  )}
                                </div>
                              ) : (
                                <div style={{ textAlign: 'center', position: 'relative', height: '100%', }}>
                                  <div style={{ position: 'absolute', top: '50%', left: '50%', transform: 'translate(-50%, -50%)',}}>
                                    <img src='/session/noAuth.jpg' />
                                    <p>暂无权限哦~请联系管理员。</p>
                                  </div>
                                </div>
                              )}
                            </Modal>
                          </div>
                        )
                      }
                      {/* 答案来源类型 - faq | modal | knowledge */}
                      {isMessageContentObjectJson && (<div className={styles['answer-generate-type']}>
                        {
                          parsedMessageContent.answerGenerateType === SessionAnswerGenerateTypeEnum.FAQ问答库
                            ? <span style={{ color: '#8fc31f' }}>本答案来自FAQ问答库，直接匹配得到。</span>
                            : parsedMessageContent.answerGenerateType === SessionAnswerGenerateTypeEnum.本地知识库
                              ? (
                                  <span style={{ color: '#0088fb' }}>
                                    本答案基于
                                    <span style={{ fontWeight: 700 }}>本地知识库</span>
                                    ，由
                                    { ` ${parsedMessageContent.modelName} ` || 'AI' }
                                    汇总回答，请谨慎参考。
                                  </span>
                                )
                              : parsedMessageContent.answerGenerateType === SessionAnswerGenerateTypeEnum.AI大模型
                                ? (
                                    <span style={{ color: '#f45b4e' }}>
                                      {
                                        parsedMessageContent.modelName
                                          ? `本答案由 ${parsedMessageContent.modelName} 直接生成，仅供参考。`
                                          : '本答案基于互联网信息，由AI自动生成，仅供参考。'
                                      }
                                    </span>
                                  )
                                : null
                        }
                      </div>)}
                      {/* 引用切片数据 */}
                      {
                        isMessageContentObjectJson &&
                        parsedMessageContent.answerDataSourceParagraphList?.length > 0 &&
                        parsedMessageContent.answerGenerateType !== SessionAnswerGenerateTypeEnum.FAQ问答库 && (
                          <div className={styles['paragraph-slice-list-wrapper']}>
                            <span className={styles['list-title']}>引用</span>
                            <ul className={styles['paragraph-slice-list']}>
                              {parsedMessageContent.answerDataSourceParagraphList.slice(0, paragraphSliceShowLength).map(
                                (paragraph: Session.ISessionDetailAnswerDataSourceParagraph) => (
                                  <li key={paragraph.docId + paragraph.paraId} className={styles['paragraph-slice-item']}
                                    onClick={() => this.handleParagraphDrawerShow(paragraph)}
                                  >
                                    {paragraph.title}
                                  </li>
                                )
                              )}
                            </ul>
                            {parsedMessageContent.answerDataSourceParagraphList.length > paragraphSliceShowLength && (
                              <div
                                className={styles['show-more']}
                                onClick={() => this.handleParagraphSliceShowLengthChange(parsedMessageContent.answerDataSourceParagraphList.length)}
                              >
                                <img src='/session/more.png' />
                              </div>
                            )}

                            <Drawer
                              height={'56%'}
                              placement='bottom'
                              title={currentParagraphSlice?.title ?? ''}
                              visible={paragraphDrawerVisible}
                              onClose={this.handleParagraphDrawerClose}
                            >
                              {currentParagraphSlice && (
                                parsedMessageContent.answerSource === 'Chat'
                                  ? (currentParagraphSlice.content &&
                                      <>
                                        {/* 渲染 Markdown */}
                                        <MarkdownRenderer
                                          markdown={currentParagraphSlice.content.replace(/<script/g, `<code>< script`).replace(/<\/script>/g, `</ script></code>`)}
                                        />
                                      </>
                                    )
                                  : (utils.isObjectJson(currentParagraphSlice.content) &&
                                      <p dangerouslySetInnerHTML={{ __html: currentParagraphSlice.content.replace(/\n/g, '<br />') }}></p>
                                    )
                              )}
                            </Drawer>
                          </div>
                        )
                      }
                      {/* 用户反馈 */}
                      {
                        /**
                         * <div className={`${styles['feedback']} ${styles['feedback-first']}`}>
                        <span className={styles['feedback-name']}>赞踩：</span>
                        <div className={styles['feedback-content']}>
                          {message.resolveFlag === 0
                            ? '无赞踩行为'
                            : message.resolveFlag === 1
                              ? '点赞'
                              : '点踩'
                          }
                        </div>
                      </div>
                      <div className={styles['feedback']}>
                        <span className={styles['feedback-name']}>评价：</span>
                        <div className={styles['feedback-content']}>
                          {message.comment || '无评价内容'}
                        </div>
                      </div>
                      <div className={styles['feedback']}>
                        <span className={styles['feedback-name']}>投诉：</span>
                        <div className={styles['feedback-content']}>
                          {message.reason || '无投诉内容'}
                        </div>
                      </div>
                         */
                      }
                    </div>
                  </div>
                </div>
              )}
            </li>
          );
        })}
      </ul>
    );
  }
}

export default SessionContext;
